home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-in_the_mag-
/
program_perfection
/
event
/
event_demo.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-03-14
|
6KB
|
277 lines
/*
* The beginnings of the event-handling module
* we talked of long ago . . .
*
* Richard Drummond 11/3/2000
*/
#include <exec/types.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
/*
* Private types
*/
typedef ULONG (*HANDLER_FUNC) (UBYTE, struct MsgPort *);
typedef struct EventHandler
{
struct MinNode eh_Node;
UBYTE eh_pad;
BYTE eh_SignalNumber; /* equivalent to ln_Pri */
struct MsgPort *eh_MsgPort; /* Where messages for this event arrive */
HANDLER_FUNC eh_HandlerFunc; /* Function to handle this event */
} HANDLER_TYPE;
typedef HANDLER_TYPE *HANDLER_PTR;
struct EventList
{
struct MinList el_HandlerList;
ULONG el_SignalMask; /* all the singals we wait for */
};
/*
* EventList_AddHandler()
*
* list - the list we wish to add to
* signum - the signal that flags this event. if this is not in the range
* 0 to 31, then we get the signal bit from the msgport.
* port - the port that this event's messages arrive at (if any)
* hfunc - function to call when event occurs
*/
BOOL
EventList_AddHandler( struct EventList *list, UBYTE signum, struct MsgPort *port, HANDLER_FUNC hfunc )
{
HANDLER_TYPE *handler;
if( signum > 31 )
signum = port->mp_SigBit;
if( handler = (HANDLER_TYPE *) AllocVec( sizeof(HANDLER_TYPE), MEMF_ANY | MEMF_CLEAR ) )
{
handler->eh_SignalNumber = signum;
handler->eh_MsgPort = port;
handler->eh_HandlerFunc = hfunc;
Enqueue( (struct List *) list, (struct Node *) handler );
list->el_SignalMask |= 1L << signum;
}
return !!handler;
}
/*
* EventList_RemHnadler()
*/
VOID
EventList_RemHandler( struct EventList *list, UBYTE signum )
{
struct Node *node = ((struct List *) list)->lh_Head;
BOOL found = FALSE;
while( node->ln_Succ && !found )
{
if( found = ( ((HANDLER_PTR)node)->eh_SignalNumber == signum ) )
break;
else
node = node->ln_Succ;
}
if( found )
{
list->el_SignalMask &= ~( 1L << ((HANDLER_PTR)node)->eh_SignalNumber );
Remove( node );
FreeVec( node );
}
}
/*
* EventList_New()
*
* Constructor for the EventList type
*/
struct EventList *
EventList_New( VOID )
{
struct EventList *list;
if( list = AllocVec( sizeof(struct EventList), MEMF_ANY ) )
{
NewList( (struct List *) list );
list->el_SignalMask = 0L;
}
return list;
}
/*
* EventList_Dispose()
*
* Destructor for the EventList type
*/
VOID
EventList_Dispose( struct EventList *list )
{
if( list )
{
struct Node *node, *temp;
node = ((struct List *) list)->lh_Head;
while( temp = node->ln_Succ )
{
FreeVec( node );
node = temp;
}
NewList( (struct List *) list );
list->el_SignalMask = 0L;
FreeVec( list );
}
}
/*
* EventList_Process()
*
* This is where it all happens.
* Put's the current process to sleep until one of the
* events in the list occurs. Then take some action
*/
ULONG
EventList_Process( struct EventList *list )
{
ULONG got_sigs;
ULONG wait_sigs = list->el_SignalMask;
struct Node *node = ((struct List *) list)->lh_Head;
ULONG ret = 0L;
if( wait_sigs )
{
got_sigs = Wait( list->el_SignalMask );
while( node->ln_Succ )
{
if( got_sigs & ( 1 << ((HANDLER_PTR)node)->eh_SignalNumber ) )
{
Printf( "Received signal: %ld\n", ((HANDLER_PTR)node)->eh_SignalNumber );
if( ((HANDLER_PTR)node)->eh_HandlerFunc )
ret = ((HANDLER_PTR)node)->eh_HandlerFunc( 0L, ((HANDLER_PTR)node)->eh_MsgPort );
}
node = node->ln_Succ;
}
}
return ret;
}
/*
* HandlerBreak()
*
* A simple handler for break signals
*/
ULONG
HandleBreak( UBYTE signal, struct MsgPort *port )
{
Printf( "**Break\n" );
return 1L;
}
/*
* HandleWindow()
*
* A simple handler for ordinary intuition windows
* It is not designed for use with a shared IDCMP port
*/
ULONG
HandleWindow( UBYTE signal, struct MsgPort *port )
{
struct IntuiMessage *temp_msg;
struct IntuiMessage imsg;
ULONG ret = 0L;
if( temp_msg = (struct IntuiMessage *) GetMsg( port ) )
{
Printf( "IntuiMessage (Class:%08lx Code:%08lx)\n", temp_msg->Class, temp_msg->Code );
/*
* Here we react to this message . . .
*
* e.g., check for the close gadget
*/
if( temp_msg->Class == IDCMP_CLOSEWINDOW )
ret=1L;
ReplyMsg( (struct Message *) temp_msg );
}
return ret;
}
/*
* A quick test . . .
*/
int main(void)
{
struct EventList *list;
if( list = EventList_New() )
{
struct Window *w;
if( w = OpenWindowTags( NULL, WA_Height, 200,
WA_Width, 200,
WA_CloseGadget, TRUE,
WA_DragBar, TRUE,
WA_SizeGadget, TRUE,
WA_SizeBBottom, TRUE,
WA_DepthGadget, TRUE,
WA_Title, "Event handling demo",
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_CHANGEWINDOW | IDCMP_RAWKEY,
TAG_DONE ) )
{
EventList_AddHandler( list, -1, w->UserPort, HandleWindow );
EventList_AddHandler( list, SIGBREAKB_CTRL_C, NULL, HandleBreak );
EventList_AddHandler( list, SIGBREAKB_CTRL_D, NULL, NULL );
EventList_AddHandler( list, SIGBREAKB_CTRL_E, NULL, NULL );
EventList_AddHandler( list, SIGBREAKB_CTRL_F, NULL, NULL );
Printf("Try pressing CTRL-C/D/E/F in this window or moving the Demo window\n");
while( !EventList_Process( list ) )
;
CloseWindow( w );
}
}
EventList_Dispose( list );
return 0L;
}